package com.lecyon.farm.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.lecyon.farm.base.BaseRequestPageVo;
import com.lecyon.farm.base.BaseRequestVo;
import com.lecyon.farm.base.BaseResponse;
import com.lecyon.farm.base.RestResponse;
import com.lecyon.farm.common.CommonService;
import com.lecyon.farm.common.constant.CommonConstant;
import com.lecyon.farm.common.constant.FarmSysConstant;
import com.lecyon.farm.common.enums.ExcelFileEnum;
import com.lecyon.farm.common.exception.FarmException;
import com.lecyon.farm.entity.DataVerification;
import com.lecyon.farm.mapper.DataVerificationMapper;
import com.lecyon.farm.service.IDataVerificationService;
import com.lecyon.farm.service.IExcelService;
import com.lecyon.farm.util.RedisUtils;
import com.lecyon.farm.util.ResultUtil;
import com.lecyon.farm.util.StringHelper;
import com.lecyon.farm.util.ValidateUtils;
import com.lecyon.farm.vo.add.AddDataVerificationVo;
import com.lecyon.farm.vo.copy.DuplicateVo;
import com.lecyon.farm.vo.export.ExportDataVerificationVo;
import com.lecyon.farm.vo.modify.ModifyDataVerificationVo;
import com.lecyon.farm.vo.query.QueryDataVerificationVo;
import com.lecyon.farm.vo.request.IdsVo;
import com.lecyon.farm.vo.status.StatusVo;
import com.lecyon.farm.vo.view.DataVerificationVo;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * 数据核检 服务实现类
 *
 * @author YaoZheng
 * @since 2020-04-25
 */
@Service
public class DataVerificationServiceImpl extends ServiceImpl<DataVerificationMapper, DataVerification> implements IDataVerificationService {

    private static final Logger LOG = LoggerFactory.getLogger(DataVerificationServiceImpl.class);

    private DataVerificationMapper mapper;

    private IExcelService excelService;

    private RedisUtils redisUtils;

    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(CommonConstant.DATE_FORMAT_PATTERN);

    /**
     * 新增或者修改
     *
     * @param entity
     * @return
     */
    @Override
    public RestResponse<Long> insertOrUpdate(DataVerification entity) {
        RestResponse<Long> result = new RestResponse<>();
        if (ValidateUtils.isNullOrEmpty(entity.getSyncDate())) {
            entity.setSyncDate(LocalDate.now(ZoneId.systemDefault()));
        }
        boolean flag;
        if (ValidateUtils.isNotNullOrEmpty(entity.getId())) {
            flag = true;
        } else {
            flag = isExist(entity.getTargetPlatform(), entity.getActivityType(), entity.getSyncDate());
        }
        if (flag) {
            // 已存在
            entity.updateById();
        } else {
            // 不存在 新增
            entity.insert();
        }
        boolean redisFlag;
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(CommonConstant.DATE_FILE_NAME_FORMAT_PATTERN);
//        String itemKey = dateFormatter.format(entity.getSyncDate());
        redisFlag = redisUtils.set(FarmSysConstant.REDIS_KEY_SYNC_DATA_VERIFICATION_TABLE, JSON.toJSONString(entity));
        if (!redisFlag) {
            LOG.error("缓存数据核检时异常");
            throw new FarmException(CommonConstant.EX_DB_REDIS_ERROR, "系统缓存异常");
        }
        return ResultUtil.success(result, entity.getId());
    }

    /**
     * 新增数据核检
     *
     * @param addVo 新增数据核检对象
     * @return 新增记录的id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResponse<Long> add(AddDataVerificationVo addVo) {
        RestResponse<Long> result = new RestResponse<>();
        //有效性校验
        //必填项校验
        //重复性校验
        boolean flag = isExist(addVo.getTargetPlatform(), addVo.getActivityType(), addVo.getSyncDate());
        if (flag) {
            // 如果记录存在，则进行编辑操作
            ModifyDataVerificationVo modifyVo = new ModifyDataVerificationVo();
            BeanUtils.copyProperties(addVo, modifyVo);
            QueryWrapper<DataVerification> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("del_flag", CommonConstant.DEL_FLAG_UNDELETED)
                    .eq("target_platform", addVo.getTargetPlatform())
                    .eq("activity_type", addVo.getActivityType())
                    .eq("sync_date", addVo.getSyncDate());
            int count = count(queryWrapper);
            if (1 == count) {
                DataVerification dataVerification = getOne(queryWrapper, true);
                modifyVo.setId(dataVerification.getId());
            } else {
                throw new FarmException(CommonConstant.TOO_MANY_RESULT_EXCEPTION, "查询结果不唯一");
            }
            return modify(modifyVo);
        }
        DataVerification entity = new DataVerification();
        BeanUtils.copyProperties(addVo, entity);
        //逻辑校验
        result = logicValidate(entity, result);
        if (!result.isSuccess()) {
            return result;
        }
        flag = entity.insert();
        if (!flag) {
            LOG.warn("DataVerification add method invoke failed. vo :{}", addVo.toString());
            return ResultUtil.error(null, CommonConstant.EX_DB_INSERT_ERROR, "新增失败！");
        }
        LOG.info("DataVerification add method invoke success. vo : {}", addVo.toString());
//        // 同步到redis中
//        String itemKey;
//        if (ValidateUtils.isNotNullOrEmpty(entity.getSyncDate())) {
//            itemKey = dateTimeFormatter.format(entity.getSyncDate());
//        } else {
//            itemKey = dateTimeFormatter.format(LocalDateTime.now(ZoneId.systemDefault()));
//        }
//        boolean redisFlag = redisUtils.hSet(FarmSysConstant.REDIS_KEY_SYNC_DATA_VERIFICATION_TABLE, itemKey, JSON.toJSONString(entity));
//        if (!redisFlag) {
//            throw new FarmException(CommonConstant.EX_DB_REDIS_ERROR, "系统缓存异常");
//        }
        return ResultUtil.success(result, entity.getId());
    }

    @Override
    public RestResponse<Long> cumulative(AddDataVerificationVo addVo) {
        return null;
    }


    /**
     * 编辑数据核检
     *
     * @param modifyVo 编辑对象
     * @return RestResponse
     */
    @Override
    public RestResponse<Long> modify(ModifyDataVerificationVo modifyVo) {
        //有效性校验
        //必填项校验
        RestResponse<Long> result = new RestResponse<>();
        DataVerification entity = new DataVerification();
        BeanUtils.copyProperties(modifyVo, entity);
        //逻辑校验
        result = logicValidate(entity, result);
        if (!result.isSuccess()) {
            return result;
        }
        boolean flag = entity.updateById();
        if (!flag) {
            LOG.warn("DataVerification modify method invoke failed. vo :{}", modifyVo.toString());
            return ResultUtil.error(null, CommonConstant.EX_DB_UPDATE_ERROR, "编辑失败！");
        }
        LOG.info("DataVerification modify method invoke success. vo : {}", modifyVo.toString());
        DataVerification currentData = getById(entity.getId());
        // 同步到redis中
//        String itemKey;
//        if (ValidateUtils.isNotNullOrEmpty(currentData.getSyncDate())) {
//            itemKey = dateTimeFormatter.format(currentData.getSyncDate());
//        } else {
//            itemKey = dateTimeFormatter.format(LocalDateTime.now(ZoneId.systemDefault()));
//        }
//        boolean redisFlag;
//        redisFlag = redisUtils.hSet(FarmSysConstant.REDIS_KEY_SYNC_DATA_VERIFICATION_TABLE, itemKey, JSON.toJSONString(currentData));
//        if (!redisFlag) {
//            throw new FarmException(CommonConstant.EX_DB_REDIS_ERROR, "系统缓存异常");
//        }
        return ResultUtil.success(result, entity.getId());
    }

    /**
     * 复制数据核检
     *
     * @param duplicateVo 复制对象Vo
     * @return
     */
    @Override
    public RestResponse<Long> duplicate(DuplicateVo duplicateVo) {
        return null;
    }

    @Override
    public BaseResponse changeStatus(StatusVo statusVo) {
        return null;
    }

    /**
     * 查看记录
     *
     * @param vo 查询条件(id)
     * @return 查询结果
     */
    @Override
    public RestResponse<DataVerificationVo> get(QueryDataVerificationVo vo) {
        RestResponse<DataVerificationVo> result = new RestResponse<>();
        if (ValidateUtils.isNullOrEmpty(vo) || ValidateUtils.isNullOrEmpty(vo.getId())) {
            return ResultUtil.error(result, CommonConstant.EX_FORM_VALIDATE_REQUIRED, "缺少必要的查询条件！");
        }
        DataVerificationVo resultVo = mapper.selectByPrimaryKey(vo);
        if (ValidateUtils.isNullOrEmpty(resultVo)) {
            return ResultUtil.error(result, CommonConstant.EX_DB_SELECT_MISS, "未找到符合条件的记录！");
        }
        return ResultUtil.success(result, resultVo);
    }

    /**
     * 查询列表
     *
     * @param vo 查询条件(包含分页）
     * @return 查询结果
     */
    @Override
    public RestResponse<Page<DataVerificationVo>> getPageList(BaseRequestPageVo<QueryDataVerificationVo> vo) {
        RestResponse<Page<DataVerificationVo>> result = new RestResponse<>();
        QueryDataVerificationVo queryCondition = vo.getEntity(QueryDataVerificationVo.class);
        Page<DataVerificationVo> page = new Page<>(vo.getPageNum(), vo.getPageSize());
        if (CollectionUtils.isNotEmpty(vo.getOrders())) {
            List<OrderItem> orderItemList = CommonService.batchAddPrefix4OrderColumn(vo.getOrders());
            page.setOrders(orderItemList);
        } else {
            page.setOrders(CommonConstant.orderItemList);
        }
        page = mapper.selectByPage(page, queryCondition);
        return ResultUtil.success(result, page);
    }

    /**
     * 查询列表
     *
     * @param vo 查询条件（不含分页信息）
     * @return 查询结果
     */
    @Override
    public RestResponse<List<DataVerificationVo>> getList(BaseRequestVo<QueryDataVerificationVo> vo) {
        RestResponse<List<DataVerificationVo>> result = new RestResponse<>();
        QueryDataVerificationVo queryCondition = vo.getEntity(QueryDataVerificationVo.class);
        List<DataVerificationVo> resultVoList = mapper.selectByCondition(queryCondition);
        return ResultUtil.success(result, resultVoList);
    }

    /**
     * 根据条件查询结果,并导出到Excel
     *
     * @param vo 查询条件
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResponse<String> exportExcel(BaseRequestVo<QueryDataVerificationVo> vo) {
        RestResponse<String> result = new RestResponse<>();
        List<ExportDataVerificationVo> resultList = Lists.newArrayList();
        RestResponse<List<DataVerificationVo>> queryResult = getList(vo);
        List<DataVerificationVo> voList = null;
        if (queryResult.isSuccess()) {
            voList = queryResult.getData();
        }
        if (CollectionUtils.isNotEmpty(voList)) {
            for (DataVerificationVo temp : voList) {
                ExportDataVerificationVo exportVo = new ExportDataVerificationVo();
                BeanUtils.copyProperties(temp, exportVo);
                resultList.add(exportVo);
            }
        }
        String downLoadUrl;
        try {
            downLoadUrl = excelService.exportExcel(resultList, ExcelFileEnum.FM_WORK);
            if (StringHelper.isEmpty(downLoadUrl)) {
                return ResultUtil.success(result, downLoadUrl);
            }
        } catch (IOException e) {
            throw new FarmException(CommonConstant.EX_EXCEL_ERROR, e.getMessage());
        }
        return ResultUtil.success(result, downLoadUrl);
    }

    /**
     * 通用删除方法，包含批量删除与单条删除
     *
     * @param vo 删除条件
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse delete(@NotNull IdsVo vo) {
        if (ValidateUtils.isNullOrEmpty(vo.getId()) && CollectionUtils.isEmpty(vo.getIdsList())) {
            LOG.warn("DataVerification delete params is null.", this.getClass().getSimpleName());
            return ResultUtil.error(CommonConstant.EX_FORM_VALIDATE_REQUIRED, "缺少必要的参数！");
        }
        List<Long> idsList = vo.getIdsList();
        if (CollectionUtils.isNotEmpty(idsList)) {
            //如果idList不为空，优先进行批量删除
            return deleteByIds(idsList);
        }
        Long id = vo.getId();
        return deleteById(id);
    }

    /**
     * 删除数据核检
     *
     * @param id 主键ID
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse deleteById(Long id) {
        boolean flag = removeById(id);
        if (!flag) {
            LOG.error("DataVerification delete unsuccessful. id :{}", id);
            return ResultUtil.error(CommonConstant.EX_DB_DELETE_ERROR, "删除记录失败！");
        }
        return ResultUtil.success();
    }

    /**
     * 批量删除数据核检
     *
     * @param idList 主键ID列表
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse deleteByIds(List<Long> idList) {
        boolean flag = removeByIds(idList);
        if (!flag) {
            LOG.error("DataVerification delete batch unsuccessful. ids :{}", idList);
            return ResultUtil.error(CommonConstant.EX_DB_DELETE_ERROR, "批量删除失败");
        }
        return ResultUtil.success();
    }

    /**
     * 逻辑校验规则
     *
     * @param entity       被校验的实体类
     * @param restResponse 消息传递对象
     * @return 结果
     */
    private RestResponse logicValidate(DataVerification entity, RestResponse restResponse) {
        return ResultUtil.success(restResponse, null);
    }

    /**
     * 查询记录是否重复
     * 标准：作业编号
     *
     * @param targetPlatform 目标平台
     * @param activityType   作业类型
     * @param syncDate       同步日期
     * @return
     */
    private boolean isExist(String targetPlatform, Integer activityType, LocalDate syncDate) {
        if (StringHelper.isEmpty(targetPlatform) || ValidateUtils.isNullOrEmpty(activityType) || ValidateUtils.isNullOrEmpty(syncDate)) {
            return false;
        }
        int count = mapper.selectCount(new QueryWrapper<DataVerification>()
                .eq("target_platform", targetPlatform)
                .eq("activity_type", activityType)
                .eq("sync_date", syncDate)
                .eq("del_flag", CommonConstant.DEL_FLAG_UNDELETED));
        return count > 0 ? true : false;
    }

    /**
     * ----------------------------- 分割线 以下是setter方法，用于替换field上的@Autowired -----------------------------
     **/

    @Autowired
    public void setMapper(DataVerificationMapper mapper) {
        this.mapper = mapper;
    }

    @Autowired
    @Lazy
    public void setExcelService(IExcelService excelService) {
        this.excelService = excelService;
    }

    @Autowired
    @Lazy
    public void setRedisUtils(RedisUtils redisUtils) {
        this.redisUtils = redisUtils;
    }

}
